package be.jaisy.project.adapter.factory.impl;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.osgi.framework.Bundle;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;

import be.jaisy.adapter.hibernate.manager.SessionFactoryManager;
import be.jaisy.osgi.transaction.ITransactionManager;
import be.jaisy.project.adapter.factory.TransactionFactory;

public class HibernateTransactionFactoryImpl extends TransactionFactory {

	private static String SESSION_FACTORY_ID = "JaisyDB";
	
	/**
	 * @see org.osgi.framework.ServiceFactory#getService(org.osgi.framework.Bundle, org.osgi.framework.ServiceRegistration)
	 */
	public Object getService(Bundle bundle, ServiceRegistration registration) {
		ServiceReference transactionServiceReference = bundle.getBundleContext().getServiceReference(ITransactionManager.class.getName());
		if (registration.getReference().equals(transactionServiceReference)) {			
			return getTransactionManager();
		}
		return null;
	}

	/**
	 * @see org.osgi.framework.ServiceFactory#ungetService(org.osgi.framework.Bundle, org.osgi.framework.ServiceRegistration, java.lang.Object)
	 */
	public void ungetService(Bundle bundle, ServiceRegistration registration, Object service) {
		//do nothing
	}
	
	@Override
	public ITransactionManager getTransactionManager() {
		return new ITransactionManager(){

			/**
			 * @see be.jaisy.osgi.transaction.ITransactionManager#beginTransaction()
			 */
			public void beginTransaction() {
				getSession().beginTransaction();			
			}

			/**
			 * @see be.jaisy.osgi.transaction.ITransactionManager#commitTransaction()
			 */
			public void commitTransaction() {
				getTransaction().commit();				
			}

			/**
			 * @see be.jaisy.osgi.transaction.ITransactionManager#flushTransaction()
			 */
			public void flushTransaction() {
				getSession().flush();
			}

			/**
			 * @see be.jaisy.osgi.transaction.ITransactionManager#rollbackTransaction()
			 */
			public void rollbackTransaction() {
				getTransaction().rollback();
			}			
		};
	}

	protected Transaction getTransaction() {
		Session session = getSession();
		if (session.getTransaction() == null)
			throw new IllegalStateException("Session.Transaction from sessionFactory [" + SESSION_FACTORY_ID + "] is not initialized before usage on DAO ");
		return session.getTransaction();
	}
	
	protected Session getSession() {
		SessionFactory sessionFactory = SessionFactoryManager.getInstance().getSessionFactory(SESSION_FACTORY_ID);
		if (sessionFactory == null)
			throw new IllegalStateException("SessionFactory [" + SESSION_FACTORY_ID + "] is not registered before usage on DAO ");
		Session session = sessionFactory.getCurrentSession();
		if (session == null)
			throw new IllegalStateException("Session from sessionFactory [" + SESSION_FACTORY_ID + "] is not initialized before usage on DAO ");
		return session;
	}
}
